package com.zte.claa.inficombo.csa.app.service.rptparse.ext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.script.Invocable;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zte.claa.inficombo.csa.app.comm.csif.CSIFCmdBuilder;
import com.zte.claa.inficombo.csa.app.comm.csif.CSIFCommService;
import com.zte.claa.inficombo.csa.app.model.dev.DevBase;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmData;
import com.zte.claa.inficombo.csa.app.service.jsplugin.JSParam;
import com.zte.claa.inficombo.csa.app.service.rptparse.AppCmdWrapper;
import com.zte.claa.inficombo.csa.app.service.rptparse.MultiPackageData;
import com.zte.claa.inficombo.csa.app.service.rptparse.ParserUpdata;
import com.zte.claa.inficombo.csa.app.service.rptparse.SensorOrgData;
import com.zte.claa.inficombo.csa.app.util.JsonUtils;

/** 
 * @author 0283000115
 * 
 * 备注：
 * 本解析子类，主要用于fntype=2048类型的第三方DTU转接“一拖多”设备及其关联的传感终端的数据解析。
 * 根据约定，第三方DTU及其连接的传感终端，数据解析主要流程包括如下几步：
 * 1、分包接收及组包（可选流程）；
 * 2、数据报文一次解析（组包完整后的初次解析，主要拆解为各sensor对应的原始码流，必选流程）；
 * 3、各传感设备子报文二次解析（根据一次解析的结果识别出各sensor，调用对应js插件做二次解析）；
 * 4、解析结果持久化及发布。
 */
public class ThirdPartyDtuUpdataSubParser extends ParserUpdata implements UpDataSubParser {
	// subparser类型key.
	public static final String PARSER_TP_3RDDTU = "sp_3rd_dtu_parser";
	
	// 一次解析的中间结果类型标记.
	public static final String UPD_KEY_SENSORDATA  = "sensorgdata";
	public static final String UPD_KEY_SENSORDATALIST = "sensordatalist";
	
	// 日志记录.
	private Logger logger = LoggerFactory.getLogger(ThirdPartyDtuUpdataSubParser.class);

	@Override
	public String getParserType() {
		return PARSER_TP_3RDDTU;
	}

	/**
	 * 总体分包；
	 * sensor一次解析；
	 * DTU自身数据解析；
	 */
	@Override
	@SuppressWarnings("unchecked")
	public void parseUpData(JSONObject json, DevBase dev, CSIFCommService svr) throws Exception {
		String devTypeId = dev.getDevType();
		// 3.根据devtype获取解析插件（缓存）
		Invocable jsRunner = this.container.getJsPnpService().getJsPLugin(devTypeId);
		if(jsRunner == null){
			logger.error("[*!!*]Can not find the JS plugin for devtype="+devTypeId);
			return;
		}
		// 解析其他payload数据.
		String portStr = JsonUtils.getJsonAttrVal(json, "port", "0");
		String payload = JsonUtils.getJsonAttrVal(json, "payload", null);
		String devEui = dev.getDevEui();
		// 自研lora定位产品会有detail信息.
		JSONObject detailJson = JsonUtils.getSubObject(json, "detail");
		byte[] payloadBS = CSIFCmdBuilder.base64Decode(payload);
		JSParam jsParam = new JSParam();
		jsParam.setDeveui(devEui);
		jsParam.setDevtypeid(devTypeId);
		jsParam.setDevport(portStr);
		jsParam.setAppeui(dev.getAppEui());
		jsParam.setProjectid(dev.getProjectId());
		jsParam.appendPara(JSParam.UPDATA_PARA_NAME, payloadBS);
		if(detailJson != null){
			jsParam.appendPara(JSParam.DETAIL_PARA_NAME, detailJson);
		}
		// 如果涉及分包，则尝试设置分包中间结果.
		MultiPackageData mpd = this.container.getMultiPkgData(devEui);
		if(mpd != null){
			jsParam.appendPara(JSParam.MULTIPKG_PARA_NAME, mpd);
		}		
		// 模型附加配置信息
		String devExtData = dev.getDatajson();
		if (devExtData != null && !devExtData.trim().equals("")) {
			try {
				jsParam.setDevExtDatas(JsonUtils.jsonStrToHashMap(devExtData));
			} catch (Exception err) {
				logger.error("Get devextdata failed: " + devExtData + ", err=" + err.getMessage());
			}
		}
		// 设置持久化服务...
		jsParam.setPersistSvr(this.container.getPersisService());
		Object rptData = jsRunner.invokeFunction(JSParam.UPDATA_PARSE_FUNC, jsParam);
		// 情况1--解析结果无效；
		if(rptData == null){
			logger.info("[*!*]Invalid or nouse report data!");
			return;
		}
		// 情况2--只有alarm数据；	
		else if(AlarmData.class.isInstance(rptData)){
			logger.debug("Alarm data return from js plugin: "+rptData);
			this.parseAlarmData((AlarmData)rptData);
			return;
		}		
		// 情况3.1--只有metedata数据；
		else if(String.class.isInstance(rptData)){
			logger.debug("Mete data return from js plugin: "+rptData.toString());
			this.parseMeteData(dev, rptData.toString(), portStr);
			return;
		}		
		// 3.2 SensorOrgData 二次解析.
		else if (SensorOrgData.class.isInstance(rptData)){
			logger.debug("3rd-DTU sensor dev data reparse: "+rptData.toString());
			this.reParseSensorOrgData((SensorOrgData)rptData, dev, portStr);
			return;
		}
		// 3.3 分包情况对象.
		else if (MultiPackageData.class.isInstance(rptData)){
			logger.debug("Multi-package data return from js plugin: "+rptData.toString());
			MultiPackageData tmpMpd = (MultiPackageData)rptData;
			tmpMpd.setAppeui(dev.getAppEui());
			tmpMpd.setDeveui(devEui);
			tmpMpd.setDevName(dev.getDevName());
			tmpMpd.setDevtype(devTypeId);
			tmpMpd.setPortStr(portStr);
			tmpMpd.setProjectid(dev.getProjectId());	
			this.processMultiPkgData(tmpMpd, jsRunner, dev, portStr);
		}
		// 情况4--同时有metedata、alarm数据、ackcmd（一种或几种兼有）；
		else if(HashMap.class.isInstance(rptData)){
			Map<String, Object> map = (HashMap<String, Object>)rptData;
			// 4.1单条告警...
			Object ao = map.get(UPD_KEY_ALARM);
			if (ao != null && AlarmData.class.isInstance(ao)) {
				logger.debug("Alarm data return from js plugin: " + ao);
				try {
					this.parseAlarmData((AlarmData) ao);
				} catch (Exception ex) {
					logger.error("parseAlarmData failed: " + ao, ex);
				}
			}
			// 4.2告警列表...
			Object aoList = map.get(UPD_KEY_ALARMLIST);
			if (aoList != null && ArrayList.class.isInstance(aoList)) {
				logger.debug("Alarm data list return from js plugin: " + aoList);
				ArrayList<AlarmData> alarmList = (ArrayList<AlarmData>) aoList;
				for (AlarmData alarm : alarmList) {
					try {
						this.parseAlarmData(alarm);
					} catch (Exception ex) {
						logger.error("parseAlarmData failed: " + alarm, ex);
					}
				}
			}		
			// 4.3单条mdata（仅限于模型字段的json字符串）...
			Object mo = map.get(UPD_KEY_METEDATA);
			if (mo != null && String.class.isInstance(mo)) {
				logger.debug("Mete data return from js plugin: " + mo);
				try {
					this.parseMeteData(dev, mo.toString(), portStr);
				} catch (Exception ex) {
					logger.error("parseMeteData failed: " + mo, ex);
				}
			}
			// 4.4mdata列表（仅限于模型字段的json字符串）...
			Object moList = map.get(UPD_KEY_METEDATALIST);
			if (moList != null && ArrayList.class.isInstance(moList)) {
				logger.debug("Mete data list return from js plugin: " + moList);
				ArrayList<String> mdataList = (ArrayList<String>) moList;
				this.parseMeteDataByBatch(dev, mdataList, portStr);
			}
			// 4.5个别设备需要回复响应确认...
			Object ackCmd = map.get(UPD_KEY_ACKCMD);
			if (ackCmd != null && AppCmdWrapper.class.isInstance(ackCmd)) {
				logger.debug("Ack command return from js plugin: " + ackCmd);
				try {
					AppCmdWrapper cmdWrapper = (AppCmdWrapper)ackCmd;
					// send cmd in async way...
					this.container.sendDevCtrlCmd(cmdWrapper);
				} catch (Exception ex) {
					logger.error("Send ack cmd failed: " + ackCmd, ex);
				}
			}
			// 4.6 个别涉及分包情况.
			Object multiPkgObj = map.get(UPD_KEY_MULTIPKG);
			if(multiPkgObj != null && MultiPackageData.class.isInstance(multiPkgObj)){
				logger.debug("Multipackage data return from js plugin: " + multiPkgObj);
				try {
					MultiPackageData tmpMpd = (MultiPackageData)multiPkgObj;
					tmpMpd.setAppeui(dev.getAppEui());
					tmpMpd.setDeveui(devEui);
					tmpMpd.setDevName(dev.getDevName());
					tmpMpd.setDevtype(devTypeId);
					tmpMpd.setPortStr(portStr);
					tmpMpd.setProjectid(dev.getProjectId());					
					this.processMultiPkgData(tmpMpd, jsRunner, dev, portStr);
				} catch (Exception ex) {
					logger.error("Multipackage data process failed: " + multiPkgObj, ex);
				}
			}
			// 4.7 SensorOrgData的二次解析.
			Object sdo = map.get(UPD_KEY_SENSORDATA);
			if (sdo != null && SensorOrgData.class.isInstance(sdo)) {
				logger.debug("Sensor org data return from js plugin: " + sdo);
				try {
					this.reParseSensorOrgData((SensorOrgData)sdo, dev, portStr);
				} catch (Exception ex) {
					logger.error("parseSensorOrgData failed: " + sdo, ex);
				}
			}
			// 4.8 SensorOrgData列表...
			Object sdoList = map.get(UPD_KEY_SENSORDATALIST);
			if (sdoList != null && ArrayList.class.isInstance(sdoList)) {
				logger.debug("Sensor org data list return from js plugin: " + sdoList);
				ArrayList<SensorOrgData> sensorOrgDataList = (ArrayList<SensorOrgData>) sdoList;
				for(SensorOrgData sensorOrgData : sensorOrgDataList){
					try {
						this.reParseSensorOrgData(sensorOrgData, dev, portStr);
					} catch (Exception ex) {
						logger.error("[2]parseSensorOrgData failed: " + sensorOrgData, ex);
					}
				}
			}	
		}	
		else {
			logger.warn("[*!*]Result data is invalid from js-plugin for devtype: "+devTypeId+", data="+rptData);
		}
	} 

	/**
	 * 一、解析框架部分的主要逻辑：
	 * 1、如果当前MPD不空，则与返回结果合并(调用container.merge方法.)；
	 * 2、如果MPD.isDataOk=yes，isParsed=yes,confirm=yes，则此时JS已经做了metedata解析和ackcmd下发；MPD从缓存删除；调外部扩展接口；
	 * 3、如果MPD.isDataOk=yes，isParsed=yes,confirm=NO，  则此时JS已经做了metedata解析，框架侧走metedata解析流程；MPD入缓存；
	 * 4、如果MPD.isDataOk=yes，isParsed=no, confirm=NO，  则此时JS未做metedata解析，触发二次解析，设置isparsed=yes；MPD入缓存；
	 * 5、如果MPD.isDataOk=yes，isParsed=no, confirm=yes，则此时JS未做metedata解析，触发二次解析，设置isparsed=yes；MPD入缓存；
	 * 6、如果MPD.isDataOk=NO，confirm=yes，则此时JS已经做了ackcmd下发，框架侧走相应ACK流程；MPD入缓存；
	 * 7、如果MPD.isDataOk=NO，confirm=NO，此时MPD入缓存，等待后续包；
	 * 
	 * 二、相应地JS插件内部逻辑：（注意确认包序号是从1开始还是从0开始，JS-Framework约定从1开始）
	 * 1、接收原始byte[]流-bs，并尝试从JSParam中获取multipkgdata参数-mpd；
	 * 2、如果mpd参数为空，则创建一个mpd对象；
	 * 3、当前bs是普通分包数据包，则解析分包数据，确定包序号；
	 * 	   3.1 将包append到mpd中，注意：判断是否出现重复包，如果出现则将mpd重新初始化；
	 * 	   3.2 判断mpd是否dataok；
	 *     3.3 如果dataok，则调用buildData()解析出metedata（本次GNSS设备不需要，其他普通分包类型的情况需要），设置isparsed=yes；
	 *     3.4返回mpd及metedata（本次GNSS不需要），特别地，如果GNSS服务器只需要GNSS终端的净荷，还涉及data的特殊处理.
	 * 4、当前bs是分包上行校验包（分包发送完毕后的确认消息）；
	 *	   4.1 设置mpd的confirmed值=1；
	 *	   4.2 获取确认位图（getBitmap）及构造ackcmd，使用全1模式（ignoreabsentpkg=true）；
	 *	   4.3返回mpd和ackcmd；
	 * 5、新增二次解析方法入口： UPDATA_MULTIPKG_REPARSE_FUNC = "funcmultipkgreparse";
	 * 	   5.1框架针对分包的类型调用，入参是mpd；
	 *     5.2调用buildData()，得到完整码流，解析码流返回metedata（可选）和mpd（设置isparsed=yes）；
	 */
	protected void processMultiPkgData(MultiPackageData mpd, Invocable jsRunner, DevBase dev, String portStr) throws Exception {
		if(mpd == null){
			return;
		}
		String devEui = dev.getDevEui();
		// 加锁互斥，避免重复处理.
		synchronized (devEui) {
			MultiPackageData mergeData = this.container.mergePackageData(mpd);
			if(mergeData == null){
				return;
			}
			boolean isConfirmed = (mergeData.getIsConfirmed() == MultiPackageData.CONFIRMED_YES);
			boolean isDataOk = mergeData.isDataOk();
			boolean isParsed = (mergeData.getIsParsed() == MultiPackageData.PARSED_YES);
			if (isDataOk && isParsed && isConfirmed) {
				this.container.removeMultiPkgData(mpd.getDeveui());
			} else if (isDataOk && !isParsed) {
				// 首先设置解析标记.
				mergeData.setIsParsed(MultiPackageData.PARSED_YES);
				this.container.setMultiPkgData(mergeData);
				// 分包收集完整后进行二次解析
				this.reParseMultiPkgData(mergeData, jsRunner, dev, portStr);
				this.container.removeMultiPkgData(mpd.getDeveui());
				logger.info("reParseMultiPkgData: " + mergeData);
			} else if (isDataOk && isParsed && !isConfirmed) {
				this.container.setMultiPkgData(mergeData);
			} else if (!isDataOk && isConfirmed) {
				this.container.setMultiPkgData(mergeData);
			} else if (!isDataOk && !isConfirmed) {
				this.container.setMultiPkgData(mergeData);
			}
		}
	}

	/**
	 * 分包收集完整后进行补充解析
	 * 
	 * @param mpd
	 * @param jsRunner
	 */
	@SuppressWarnings("unchecked")
	protected void reParseMultiPkgData(MultiPackageData mpd, Invocable jsRunner, DevBase dev, String portStr) throws Exception {
		// 设置可能的扩展配置数据，供js插件访问.
		this.setExtDataToMultiPkg(mpd, dev);
		// 组包完整后的一次解析.
		Object rptData = jsRunner.invokeFunction(JSParam.UPDATA_MULTIPKG_REPARSE_FUNC, mpd);
		// 情况1--解析结果无效；
		if(rptData == null){
			logger.info("[*!*]MPD-Reparse: Invalid or nouse report data!");
			return;
		}
		// 情况2--只有alarm数据；	
		else if(AlarmData.class.isInstance(rptData)){
			logger.debug("MPD-Reparse: Alarm data return from js plugin: "+rptData);
			this.parseAlarmData((AlarmData)rptData);
			return;
		}		
		// 情况3.1--只有metedata数据；
		else if(String.class.isInstance(rptData)){
			logger.debug("MPD-Reparse: Mete data return from js plugin: "+rptData.toString());
			this.parseMeteData(dev, rptData.toString(), portStr);
			return;
		}	
		// 3.2 SensorOrgData 二次解析.
		else if (SensorOrgData.class.isInstance(rptData)){
			logger.debug("claa sensor dev data reparse: "+rptData.toString());
			this.reParseSensorOrgData((SensorOrgData)rptData, dev, portStr);
			return;
		}
		// 情况4--同时有metedata、alarm数据、ackcmd（一种或几种兼有）；
		else if(HashMap.class.isInstance(rptData)){
			Map<String, Object> map = (HashMap<String, Object>)rptData;
			// 4.1单条告警...
			Object ao = map.get(UPD_KEY_ALARM);
			if (ao != null && AlarmData.class.isInstance(ao)) {
				logger.debug("Alarm data return from js plugin: " + ao);
				try {
					this.parseAlarmData((AlarmData) ao);
				} catch (Exception ex) {
					logger.error("parseAlarmData failed: " + ao, ex);
				}
			}
			// 4.2告警列表...
			Object aoList = map.get(UPD_KEY_ALARMLIST);
			if (aoList != null && ArrayList.class.isInstance(aoList)) {
				logger.debug("Alarm data list return from js plugin: " + aoList);
				ArrayList<AlarmData> alarmList = (ArrayList<AlarmData>) aoList;
				for (AlarmData alarm : alarmList) {
					try {
						this.parseAlarmData(alarm);
					} catch (Exception ex) {
						logger.error("parseAlarmData failed: " + alarm, ex);
					}
				}
			}		
			// 4.3单条mdata（仅限于模型字段的json字符串）...
			Object mo = map.get(UPD_KEY_METEDATA);
			if (mo != null && String.class.isInstance(mo)) {
				logger.debug("Mete data return from js plugin: " + mo);
				try {
					this.parseMeteData(dev, mo.toString(), portStr);
				} catch (Exception ex) {
					logger.error("parseMeteData failed: " + mo, ex);
				}
			}
			// 4.4mdata列表（仅限于模型字段的json字符串）...
			Object moList = map.get(UPD_KEY_METEDATALIST);
			if (moList != null && ArrayList.class.isInstance(moList)) {
				logger.debug("Mete data list return from js plugin: " + moList);
				ArrayList<String> mdataList = (ArrayList<String>) moList;
				this.parseMeteDataByBatch(dev, mdataList, portStr);
			}			
			// 4.5 SensorOrgData的二次解析.
			Object sdo = map.get(UPD_KEY_SENSORDATA);
			if (sdo != null && SensorOrgData.class.isInstance(sdo)) {
				logger.debug("Sensor org data return from js plugin: " + sdo);
				try {
					this.reParseSensorOrgData((SensorOrgData)sdo, dev, portStr);
				} catch (Exception ex) {
					logger.error("parseSensorOrgData failed: " + sdo, ex);
				}
			}
			// 4.6SensorOrgData列表...
			Object sdoList = map.get(UPD_KEY_SENSORDATALIST);
			if (sdoList != null && ArrayList.class.isInstance(sdoList)) {
				logger.debug("Sensor org data list return from js plugin: " + sdoList);
				ArrayList<SensorOrgData> sensorOrgDataList = (ArrayList<SensorOrgData>) sdoList;
				for(SensorOrgData sensorOrgData : sensorOrgDataList){
					try {
						this.reParseSensorOrgData(sensorOrgData, dev, portStr);
					} catch (Exception ex) {
						logger.error("[2]parseSensorOrgData failed: " + sensorOrgData, ex);
					}
				}
			}		
			// 4.7个别设备需要回复响应确认...
			Object ackCmd = map.get(UPD_KEY_ACKCMD);
			if (ackCmd != null && AppCmdWrapper.class.isInstance(ackCmd)) {
				logger.debug("Ack command return from js plugin: " + ackCmd);
				try {
					AppCmdWrapper cmdWrapper = (AppCmdWrapper)ackCmd;
					// send cmd in async way...
					this.container.sendDevCtrlCmd(cmdWrapper);
				} catch (Exception ex) {
					logger.error("Send ack cmd failed: " + ackCmd, ex);
				}
			}
		}
		else {
			logger.warn("[*!!*]Result data is invalid from js-plugin for devtype: "+dev.getDevType()+", data="+rptData);
		}
	}
	
	/**
	 * 传感终端数据的二次解析.
	 * 
	 * @param sensorData
	 * @param dev
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private void reParseSensorOrgData(SensorOrgData sensorData, DevBase dtudev, String portStr) throws Exception {
		if(sensorData == null){
			return;
		}
		sensorData.setDtueui(dtudev.getDevEui());
		String sensorEui = sensorData.getSensorEui();
		DevBase sensordev = this.container.getCacheManager().getDev(sensorEui);
		if(sensordev == null){
			logger.error("[*@@*]Sensor-Dev not exist in local cache/db: "+sensorEui);
			return;
		}
		String devTypeId = sensordev.getDevType();		
		Invocable jsRunner = this.container.getJsPnpService().getJsPLugin(devTypeId);
		if(jsRunner == null){
			logger.error("[*!!*]Can not find the JS plugin for devtype="+devTypeId+", sensor="+sensorEui);
			return;
		}
		byte[] payloadBS = sensorData.getPayload();
		JSParam jsParam = new JSParam();
		jsParam.setDeveui(sensorEui);
		jsParam.setDevtypeid(devTypeId);
		jsParam.setDevport(portStr);
		jsParam.setAppeui(dtudev.getAppEui());
		jsParam.setProjectid(dtudev.getProjectId());
		jsParam.appendPara(JSParam.UPDATA_PARA_NAME, payloadBS);	
		// 模型附加配置信息
		String devExtData = sensordev.getDatajson();
		if (devExtData != null && !devExtData.trim().equals("")) {
			try {
				jsParam.setDevExtDatas(JsonUtils.jsonStrToHashMap(devExtData));
			} catch (Exception err) {
				logger.error("Get devextdata failed: " + devExtData + ", err=" + err.getMessage());
			}
		}
		// 设置持久化服务...
		jsParam.setPersistSvr(this.container.getPersisService());
		Object rptData = jsRunner.invokeFunction(JSParam.UPDATA_PARSE_FUNC, jsParam);
		// 情况1--解析结果无效；
		if(rptData == null){
			logger.info("[*!*]Invalid or nouse report data for sensor: "+sensorEui);
			return;
		}
		// 情况2--只有alarm数据；	
		else if(AlarmData.class.isInstance(rptData)){
			logger.debug("Alarm data return from js plugin: "+rptData);
			this.parseAlarmData((AlarmData)rptData);
			return;
		}		
		// 情况3--只有metedata数据；
		else if(String.class.isInstance(rptData)){
			logger.debug("Mete data return from js plugin: "+rptData.toString());
			this.parseMeteData(sensordev, rptData.toString(), portStr);
			return;
		}
		// 情况4--同时有metedata、alarm数据、ackcmd等（一种或几种兼有）；
		else if(HashMap.class.isInstance(rptData)){
			Map<String, Object> map = (HashMap<String, Object>)rptData;
			// 4.1单条告警...
			Object ao = map.get(UPD_KEY_ALARM);
			if (ao != null && AlarmData.class.isInstance(ao)) {
				logger.debug("Alarm data return from js plugin: " + ao);
				try {
					this.parseAlarmData((AlarmData) ao);
				} catch (Exception ex) {
					logger.error("parseAlarmData failed: " + ao, ex);
				}
			}
			// 4.2告警列表...
			Object aoList = map.get(UPD_KEY_ALARMLIST);
			if (aoList != null && ArrayList.class.isInstance(aoList)) {
				logger.debug("Alarm data list return from js plugin: " + aoList);
				ArrayList<AlarmData> alarmList = (ArrayList<AlarmData>) aoList;
				for (AlarmData alarm : alarmList) {
					try {
						this.parseAlarmData(alarm);
					} catch (Exception ex) {
						logger.error("parseAlarmData failed: " + alarm, ex);
					}
				}
			}		
			// 4.3单条mdata（仅限于模型字段的json字符串）...
			Object mo = map.get(UPD_KEY_METEDATA);
			if (mo != null && String.class.isInstance(mo)) {
				logger.debug("Mete data return from js plugin: " + mo);
				try {
					this.parseMeteData(sensordev, mo.toString(), portStr);
				} catch (Exception ex) {
					logger.error("parseMeteData failed: " + mo, ex);
				}
			}
			// 4.4mdata列表（仅限于模型字段的json字符串）...
			Object moList = map.get(UPD_KEY_METEDATALIST);
			if (moList != null && ArrayList.class.isInstance(moList)) {
				logger.debug("Mete data list return from js plugin: " + moList);
				ArrayList<String> mdataList = (ArrayList<String>) moList;
				this.parseMeteDataByBatch(sensordev, mdataList, portStr);
			}
			// 4.5个别设备需要回复响应确认...
			Object ackCmd = map.get(UPD_KEY_ACKCMD);
			if (ackCmd != null && AppCmdWrapper.class.isInstance(ackCmd)) {
				logger.debug("Ack command return from js plugin: " + ackCmd);
				try {
					AppCmdWrapper cmdWrapper = (AppCmdWrapper)ackCmd;
					// send cmd in async way...
					this.container.sendDevCtrlCmd(cmdWrapper);
				} catch (Exception ex) {
					logger.error("Send ack cmd failed: " + ackCmd, ex);
				}
			}
		}
		else {
			logger.warn("[*!!!*]Result data is invalid from js-plugin for devtype: "+devTypeId+", data="+rptData);
		}
	}
	
}
